<?php
namespace Twoir\Service;

use Exception;
use Twoir\System\Model\EnewsMember;
use Twoir\System\Support\ParamTrait;

/**
 * 会员基本功能，原版专用 isLogin logout
 *
 * 2024.04.23 cighsen02 365182575
 * Update at: 2025.05.08
*/
class BaseMember
{
	use ParamTrait;
	// 当前登陆用户
	protected $user;
	// 允许字段 用户提交过滤
	const ALLOW = ['classid', 'id', 'cid', 'cname', 'add', 'del', 'edit'];
	// 简洁方式
	const SIMPLE_FIELD 	= ['userid','username','email','groupid','ingid','agid','userfen','phno','upic'];
	// 键全方式
	const FULL_FIELD 	= [
        'userid',
        'username',
        'email',
        'groupid',
        'userfen',
        'money',
        'userdate',
        'zgroupid',
        'havemsg',
        'registertime',
        'ingid',
        'agid',
        'isern',
        'isot',
        'phno',
        'upic',
        'mustdo',
        'rndt',
        'userjyz',
        'usertitle'
    ];
	// 时间
	protected $nowtime;

	protected $ip;

	protected $port;
	/**
	 * 是否强制验证登陆
	 *
	 * @param bool $verifyLogin
	*/
	public function __construct(bool $verifyLogin = true)
	{
		$this->nowtime  = time();
		$this->ip       = egetip();
		$this->port     = egetipport();

		$verifyLogin ? $this->isLogin() : $this->userInfo();
	}

	/**
	 * 是否登陆
	 *
	 * @param bool $isSimple 是否返回简洁信息 默认返回简单
	 * @return array
     *
     * @throws Exception
	*/
	protected function isLogin(bool $isSimple = true): array
	{
		$userid 	= (int)getcvar('mluserid');
		$username 	= getcvar('mlusername');
		$username	= RepPostVar($username);
		$rnd 		= getcvar('mlrnd');
		$rnd 		= RepPostVar($rnd);

		if(!$userid || !$username || !$rnd)	{

			$this->user = null;
			throw new Exception('您还没登录!', 2200);
		}

		$qcklgr = $this->qCheckLoginAuthstr();
		if(!isset($qcklgr['islogin']) || !$qcklgr['islogin'])	{

			$this->user = null;
			EmptyEcmsCookie();

			throw new Exception('同一帐号同一时刻只能一人在线!', 2200);
		}

		$field = $isSimple ? [...static::SIMPLE_FIELD, 'userdate', 'zgroupid', 'checked'] : [...static::FULL_FIELD, 'checked'];

		$cr = EnewsMember::getOne(['userid' => $userid, 'username' => $username, 'rnd' => $rnd], $field);

		if(!isset($cr['userid']) || empty($cr['userid'])){

			$this->user = null;
			EmptyEcmsCookie();

			throw new Exception('同一帐号同一时刻只能一人在线!', 2200);
		}

		if(0 == $cr['checked']){

			$this->user = null;
			EmptyEcmsCookie();

			throw new Exception('您的帐号还未通过审核', 2200);
		}

		//默认会员组
		if(empty($cr['groupid'])){

			$cr['groupid'] = eReturnMemberDefGroupid();

			EnewsMember::update(['userid' => $cr['userid']], ['groupid' => $cr['groupid']]);
		}

		//是否过期
		if($cr['userdate'] && ($cr['userdate'] - time() <= 0))	{

		    if($cr['zgroupid'])	{

		        EnewsMember::update(['userid' => $cr['userid']], ['groupid' => $cr['zgroupid'], 'userdate' => 0]);
		        $cr['zgroupid'] = 0;
		    }
		    else {

		        EnewsMember::update(['userid' => $cr['userid']], ['userdate' => 0]);
		    }

		    $cr['userdate'] = 0;
		}

		// 赋值
		$this->user = $cr;

		return $this->filter($cr, $isSimple) + $this->getLevel($cr['groupid']);
	}

	/**
	 * 退出登陆
     *
     * @return void
	*/
	public function logout()
	{
        global $ecms_config;

		// 真正退出
		if (!empty($user = $this->userInfo())) {

		    $update = [
                $this->egetmf('isot') => 0
            ];
            // 更新rnd
            if($ecms_config['sets']['mpchmrnd']) {
                $update += [
                    $this->egetmf('rnd')    => make_password(EcmsRandInt(20,36)),
                    $this->egetmf('rndt')   => make_password(EcmsRandInt(20,32))
                ];
            }

            EnewsMember::update(['userid' => $user['userid']], $update);
		}

		EmptyEcmsCookie();
	}

    /**
     * 获取字段名
     *
     * @param string $field
     * @return string
     */
    protected function egetmf(string $field): string
    {
        global $ecms_config;

        if(isset($ecms_config['member']['chmember']) || empty($ecms_config['member']['chmember']))
        {
            return $field;
        }

        return $ecms_config['memberf'][$field] ?? $field;
    }

	/**
	 * 返回登陆用户信息
	 *
	 * @return array
	*/
	public function getLoginInfo(): array
	{
		return $this->userInfo();
	}

	/**
	 * 返回已经登陆用户信息
	 *
	 * @return array
	*/
	protected function userInfo(): array
	{
		try {

			$result = $this->user ? $this->filter($this->user, true) + $this->getLevel($this->user['groupid']) : $this->isLogin();

	    }
	    catch (Exception $e) {

	        return [];
	    }

	    return $result;
	}

    /**
	 * 返回默认会员组ID
	 *
	 * @return int
	*/
	public function returnMemberDefGroupid(): int
	{
		global $ecms_config, $public_r;

		return $ecms_config['member']['defgroupid'] ? (int)$ecms_config['member']['defgroupid'] : (int)$public_r['defaultgroupid'];
	}

	/**
	 * 验证登录验证符
     *
     * @return array
	*/
	protected function qCheckLoginAuthstr(): array
	{
		global $ecms_config;

		$checkpass = getcvar('mlauth');

		if(!$checkpass) {

            return [
                'userid'   => '',
                'username' => '',
                'groupid'  => '',
                'rnd'      => '',
                'islogin'  => 0
            ];
        }

		$userid	    = (int)getcvar('mluserid');
		$username	= RepPostVar(getcvar('mlusername'));
		$rnd		= RepPostVar(getcvar('mlrnd'));
		$groupid	= (int)getcvar('mlgroupid');
        $result     = [
            'userid'   => $userid,
            'username' => $username,
            'groupid'  => $groupid,
            'rnd'      => $rnd,
        ];

		if(!$userid || !$username || !$rnd) return $result;

		$pass = md5(md5($rnd . '--d-i!' . $userid . '-(g*od-' . $username . $ecms_config['cks']['ckrndtwo'] . '-' . $groupid) . '-#empire.cms!--p)h-o!me-' . $ecms_config['cks']['ckrndtwo']);

		if($pass !== $checkpass) return $result;

		return $result + ['islogin' => 1];
	}

    /**
	 * 登录验证符
	 *
	 * @param int $userid
	 * @param string $username
	 * @param string $rnd
	 * @param int $groupid
	 * @param int $cookietime
	*/
	protected function qGetLoginAuthstr($userid, $username, $rnd, $groupid, $cookietime = 0)
	{
		global $ecms_config;

		esetcookie('mlauth', md5(md5($rnd . '--d-i!' . $userid . '-(g*od-' . $username . $ecms_config['cks']['ckrndtwo'] . '-' . $groupid) . '-#empire.cms!--p)h-o!me-' . $ecms_config['cks']['ckrndtwo']), $cookietime);
	}

    /**
	 * 清空验证码
	 *
	 * @param string $varname
	 * @param int $ecms
	 * @param int $isAdmin
	*/
	protected function emptyShowKey($varname, $ecms = 0, $isAdmin = 0)
	{
		esetcookie($varname, '', 0, $ecms);
	}

    /**
	 * 检查验证码
	 *
	 * @param string $varname
	 * @param string $postval
	 * @param int $dopr
	 * @param int $ecms
	 * @param int $isAdmin
     *
	 * @throws Exception
	*/
	protected function checkShowKey($varname, $postval, $dopr, $ecms = 0, $isAdmin = 0)
	{
		global $public_r;

		if(1 === $isAdmin){

			$pubkeytime	= $public_r['hkeytime'];
			$pubkeyrnd	= $public_r['hkeyrnd'];
		}
		else{

			$pubkeytime	= $public_r['keytime'];
			$pubkeyrnd	= $public_r['keyrnd'];
		}

		$r 		= explode(',', getcvar($varname, $ecms));
		$cktime	= isset($r[0]) ? (int)$r[0] : 0;
		$pass	= $r[1];
		$val	= $r[2];

		if($cktime > $this->nowtime || $this->nowtime - $cktime > $pubkeytime) throw new Exception('验证码已过期', 1200);

		if(empty(trim($postval))) throw new Exception('验证码验证失败', 1200);

		if(md5('d!i#g?o-d-' . md5(md5($varname . 'E.C#M!S^e-' . $postval) . '-E?m!P.i#R-e' . $cktime) . $pubkeyrnd . 'P#H!o,m^e-e') !== $pass){

			throw new Exception('验证码验证失败', 1200);
		}
	}

	/**
	 * 转换权限
	 *
	 * @param int $groupid
	 * @return array
	*/
	protected function getLevel(int $groupid): array
	{
		global $level_r;

		if (!$groupid || !isset($level_r[$groupid]) || empty($level_r[$groupid])) return [];

		return array_filter($level_r[$groupid], fn($key) => in_array($key, ['level', 'groupname']), ARRAY_FILTER_USE_KEY);
	}

	/**
	 * 去除无关数据
	 *
	 * @param array $data
	 * @param bool $isSimple
	 * @return array
	*/
	protected function filter(array $data, bool $isSimple)
	{
		return array_filter($data, fn($key) => in_array($key, $isSimple ? static::SIMPLE_FIELD : static::FULL_FIELD), ARRAY_FILTER_USE_KEY);
	}
}
